﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
using Portal.Systems.Model;
using Portal.Utility;
using Portal.Database.Service;
using Portal.Web.Utility;
using Portal.Core;
using Portal.Systems.Bussiness.Template;

namespace Portal.Systems.Bussiness
{
    public class PermissionProcessBll 
    {
        public static void InitPermisison(string SiteId, IPermission OPermissionTemplate)
        {
            IDatabaseService DBService = WebDatabaseService.CreateDBService(SiteId);
            string AssetCode = WebSessionUtility.GetCurrentLoginUser().AssetCode;
            SiteParam OSiteParam = WebEnvironments.CreateSiteParam(SiteId);
            string DataLanguage = WebConfig.GetDataLanguage(OSiteParam);
            IDbTransaction Trans=DBService.BeginTransaction();
            try
            {
                try
                {
                    DBService.Insert(Trans, "TablePermissionType", new DbParam[]{
                        new DbParam("PermissionTypeId",OPermissionTemplate.Id),
                        new DbParam("PermissionTypeName",OPermissionTemplate.PermissionTypeName)
                    });
                }
                catch(Exception ex)
                {
                    ex.Source="";
                }
                for (int iIndex = 0; iIndex < OPermissionTemplate.PermissionFunctions.Length; iIndex++)
                {
                    try
                    {
                        DBService.Insert(Trans, "TablePermissionFunction", new DbParam[]{
                                new DbParam("PermissionFunctionId",OPermissionTemplate.PermissionFunctions[iIndex].PermissionFunctionId),
                                new DbParam("FunctionName",OPermissionTemplate.PermissionFunctions[iIndex].FunctionName),
                                new DbParam("frkPermissionTypeId",OPermissionTemplate.PermissionFunctions[iIndex].PermissionTypeId),
                            });
                    }
                    catch (Exception ex)
                    {
                        ex.Source = "";
                    }
                }
                Trans.Commit();
            }
            catch (Exception ex)
            {
                Trans.Rollback();
                throw (ex);
            }
        }


        public static PermissionRoleCls[] ReadingPermissionRoles(
            string SiteId,
            string PermissionTypeId,
            string ObjectId)
        {
            IDatabaseService DBService = WebDatabaseService.CreateDBService(SiteId);
            string Query =
                " Update TablePermissionRole set DisplayInfo = ( select RoleName from tableRole where frkRoleId=RoleId) where not frkRoleId is null; " +
                " Update TablePermissionRole set DisplayInfo = ( select FullName+' - '+LoginName from TableUser where frkUserId=UserId) where not frkUserId is null; " +
                " select PermissionRoleId, ObjectId, RoleId=frkRoleId,UserId=frkUserId,Type,DisplayInfo  from TablePermissionRole where ObjectId=@ObjectId and frkPermissionTypeId=@PermissionTypeId order by Type";
            DataTable dtResult =  DBService.GetDataTable(null, Query,new DbParam[]{
                   new DbParam("ObjectId",ObjectId),
                   new DbParam("PermissionTypeId",PermissionTypeId),
               });
            PermissionRoleCls[] PermissionRole = PermissionRoleParser.ParseFromDataTable(dtResult);
            return PermissionRole;
        }

        public static string[] ReadingPermissionFunction(
            string SiteId,
            string PermissionTypeId)
        {
            IDatabaseService DBService = WebDatabaseService.CreateDBService(SiteId);
            DataTable dtRows = DBService.GetDataTable(null, "select PermissionFunctionId from TablePermissionFunction where frkPermissionTypeId=@PermissionTypeId", new DbParam[]{
                new DbParam("PermissionTypeId",PermissionTypeId)
            });
            string[] FunctionIds = new string[dtRows.Rows.Count];
            for (int iIndex = 0; iIndex < dtRows.Rows.Count; iIndex++)
            {
                FunctionIds[iIndex] = (string)dtRows.Rows[iIndex]["PermissionFunctionId"];
            }
            return FunctionIds;
        }

        public static PermissionRoleDetailCls[] ReadingPermissionRoleDetail(
            string SiteId,
            string PermissionTypeId,
            string PermissionRoleId)
        {
            string[] FunctionIds = ReadingPermissionFunction(SiteId, PermissionTypeId);
            IDatabaseService DBService = WebDatabaseService.CreateDBService(SiteId);
            for (int iIndex = 0; iIndex < FunctionIds.Length; iIndex++)
            {
                try
                {
                    DBService.Insert(null, "TablePermissionRoleDetail",
                        new DbParam[]{
                            new DbParam("PermissionRoleDetailId",System.Guid.NewGuid().ToString()),
                            new DbParam("frkPermissionRoleId",PermissionRoleId),
                            new DbParam("frkPermissionFunctionId",FunctionIds[iIndex]),
                            new DbParam("Allow",1),
                            new DbParam("ptc",PermissionTypeId)
                    });
                }
                catch { }
            }

            string Query =
                " select PermissionRoleDetailId, PermissionRoleId=frkPermissionRoleId, PermissionFunctionId, Allow, FunctionName from TablePermissionRoleDetail" +
                "   join TablePermissionFunction on TablePermissionFunction.PermissionFunctionId=frkPermissionFunctionId" +
                " where frkPermissionRoleId='" + PermissionRoleId + "'" +
                "   order by FunctionName";
            DataTable dtRows = DBService.GetDataTable(null, Query, null);
            PermissionRoleDetailCls[] PermissionRoleDetails = PermissionRoleDetailParser.ParseFromDataTable(dtRows);
            return PermissionRoleDetails;
        }

        public static void DeleteNotExistsInObject(string SiteId, string PermissionTypeId)
        {
            IPermission Found= WebPermissionUtility.Find(SiteId, PermissionTypeId);
            string[] FunctionIds = new string[Found.PermissionFunctions.Length];// ReadingPermissionFunction(SiteId, PermissionTypeId);
            for (int iIndex = 0; iIndex < FunctionIds.Length; iIndex++)
            {
                FunctionIds[iIndex] = Found.PermissionFunctions[iIndex].PermissionFunctionId;
            }
            if (FunctionIds.Length == 0) return;
            string Ids = "(";
            for (int iIndex = 0; iIndex < FunctionIds.Length; iIndex++)
            {
                Ids += "'" + FunctionIds[iIndex] + "'";
                if (iIndex < FunctionIds.Length - 1)
                {
                    Ids += ",";
                }
            }
            Ids += ")";
            string Query =
                " Delete from TablePermissionRoleDetail where ptc='" + PermissionTypeId + "' and not frkPermissionFunctionId in " + Ids + "; " +
               " Delete from TablePermissionFunction where frkPermissionTypeId='" + PermissionTypeId + "' and not PermissionFunctionId in " + Ids + "; ";
               
            IDatabaseService DBService = WebDatabaseService.CreateDBService(SiteId);
            DBService.ExecuteNonQuery(null, Query, null);
        }


        public static void InitPermissionRoleDetail(
            IDbTransaction Trans,
            string SiteId,
            string PermissionTypeId,
            string PermissionRoleId)
        {
            string[] FunctionIds = ReadingPermissionFunction(SiteId, PermissionTypeId);
            IDatabaseService DBService = WebDatabaseService.CreateDBService(SiteId);
            try
            {
                for (int iIndex = 0; iIndex < FunctionIds.Length; iIndex++)
                {
                    DBService.Insert(Trans, "TablePermissionRoleDetail",
                        new DbParam[]{
                            new DbParam("PermissionRoleDetailId",System.Guid.NewGuid().ToString()),
                            new DbParam("frkPermissionRoleId",PermissionRoleId),
                            new DbParam("frkPermissionFunctionId",FunctionIds[iIndex]),
                            new DbParam("Allow",1),
                            new DbParam("ptc",PermissionTypeId)
                    });
                }
            }
            catch { }
        }


        public static RoleCls[] ReadingRoleForPermission(
            string SiteId,
            string PermissionTypeId,
            string ObjectId,
            string AccountType,
            string Keyword)
        {
            Keyword=FunctionUtilities.CorrectForSearch(Keyword);
            IDatabaseService DBService = WebDatabaseService.CreateDBService(SiteId);
            string Query = "select TableRole.*,RoleTypeText='' from TableRole where 1=1 ";
            if (!string.IsNullOrEmpty(AccountType))
            {
                Query += " and RoleType='" + AccountType + "' ";
            }
            if (!string.IsNullOrEmpty(Keyword))
            {
                Query += " and ( RoleCode like N'%" + Keyword + "%' or RoleName like N'%" + Keyword + "%')";
            }
            Query+=
                " and RoleId not in (select frkRoleId from TablePermissionRole where not frkRoleId is null and ObjectId=@ObjectId and frkPermissionTypeId=@PermissionTypeId)";
            DataTable dtResult = DBService.GetDataTable(null, Query, new DbParam[]{
                   new DbParam("ObjectId",ObjectId),
                   new DbParam("PermissionTypeId",PermissionTypeId),
               });
            RoleCls[] Roles = RoleParser.ParseFromDataTable(dtResult);
            return Roles;
        }


        public static UserCls[] ReadingUserForPermission(
            string SiteId,
            string PermissionTypeId,
            string ObjectId,
            string AccountType,
            string Keyword)
        {
            Keyword = FunctionUtilities.CorrectForSearch(Keyword);
            IDatabaseService DBService = WebDatabaseService.CreateDBService(SiteId);
            string Query = "select TableUser.* from TableUser where 1=1 ";
            if (!string.IsNullOrEmpty(AccountType))
            {
                Query += " and UserId in (select frkUserId from TableUserType where AccountType='" + AccountType + "')";
            }
            if (!string.IsNullOrEmpty(Keyword))
            {
                Query += " and ( LoginName like N'%" + Keyword + "%' or FullName like N'%" + Keyword + "%')";
            }
            Query += " and UserId not in (select frkUserId from TablePermissionRole where not frkUserId is null and ObjectId=@ObjectId and frkPermissionTypeId=@PermissionTypeId)";
            DataTable dtResult = DBService.GetDataTable(null, Query, new DbParam[]{
                   new DbParam("ObjectId",ObjectId),
                   new DbParam("PermissionTypeId",PermissionTypeId),
               });
            UserCls[] Users = UserParser.ParseFromDataTable(dtResult);

            return Users;
        }



        public static void AddRolePermission(
            string SiteId,
            string ptc,
            string ObjectId,
            string[] RoleIds,
            string[] UserIds)
        {
            IDatabaseService DBService = WebDatabaseService.CreateDBService(SiteId);
            IDbTransaction Trans = DBService.BeginTransaction();
            try
            {
                string PermissionRoleId = "";
                for (int iIndex = 0; iIndex < RoleIds.Length; iIndex++)
                {
                    PermissionRoleId=System.Guid.NewGuid().ToString();
                    DBService.Insert(Trans, "TablePermissionRole", new DbParam[]{
                        new DbParam("PermissionRoleId",PermissionRoleId),
                        new DbParam("ObjectId",ObjectId),
                        new DbParam("frkRoleId",RoleIds[iIndex].Trim()),
                        new DbParam("Type","role"),
                        new DbParam("DisplayInfo",""),
                        new DbParam("frkPermissionTypeId",ptc),
                    });
                    InitPermissionRoleDetail(Trans, SiteId, ptc, PermissionRoleId);
                }
                for (int iIndex = 0; iIndex < UserIds.Length; iIndex++)
                {
                    PermissionRoleId = System.Guid.NewGuid().ToString();
                    DBService.Insert(Trans, "TablePermissionRole", new DbParam[]{
                        new DbParam("PermissionRoleId",PermissionRoleId ),
                        new DbParam("ObjectId",ObjectId),
                        new DbParam("frkUserId",UserIds[iIndex].Trim()),
                        new DbParam("Type","user"),
                        new DbParam("DisplayInfo",""),
                        new DbParam("frkPermissionTypeId",ptc),
                    });
                    InitPermissionRoleDetail(Trans, SiteId, ptc, PermissionRoleId);
                }
                Trans.Commit();
            }
            catch (Exception ex)
            {
                Trans.Rollback();
                throw (ex);
            }
        }


        public static PermissionRoleCls CreatePermissionRoleModel(
           string SiteId,
           string PermissionRoleId)
        {
            IDatabaseService DBService = WebDatabaseService.CreateDBService(SiteId);
            string Query =
                " select PermissionRoleId, ObjectId, RoleId=frkRoleId,UserId=frkUserId,Type,DisplayInfo  from TablePermissionRole where PermissionRoleId=@PermissionRoleId";
            DataTable dtResult = DBService.GetDataTable(null, Query, new DbParam[]{
                   new DbParam("PermissionRoleId",PermissionRoleId),
               });
            PermissionRoleCls PermissionRole = PermissionRoleParser.ParseFromDataRow(dtResult.Rows[0]);
            return PermissionRole;
        }



        public static void SetPermissionDetail(
            string SiteId, 
            string PermissionRoleId,
            string[] PermissionDetailIds)
        {
            IDatabaseService DBService = WebDatabaseService.CreateDBService(SiteId);
            SiteParam OSiteParam = WebEnvironments.CreateSiteParam(SiteId);
            string AssetCode = WebSessionUtility.GetCurrentLoginUser().AssetCode;
            string DataLanguage = WebConfig.GetDataLanguage(OSiteParam);
            IDbTransaction Trans = DBService.BeginTransaction();
            try
            {
                DBService.ExecuteNonQuery(Trans," Update TablePermissionRoleDetail set Allow=0 where frkPermissionRoleId=@PermissionRoleId",
                    new DbParam[]{
                        new DbParam("PermissionRoleId",PermissionRoleId),
                    });
                
                for(int iIndex=0;iIndex<PermissionDetailIds.Length;iIndex++)
                {
                    DBService.ExecuteNonQuery(Trans, "Update TablePermissionRoleDetail set Allow=1 where PermissionRoleDetailId=@PermissionRoleDetailId", new DbParam[]{
                        new DbParam("PermissionRoleDetailId",PermissionDetailIds[iIndex]),
                    });
                }
                
                Trans.Commit();
            }
            catch (Exception ex)
            {
                Trans.Rollback();
                throw (ex);
            }
        }


        public static void DeletePermissionRole(
            string SiteId,
            string PermissionRoleId)
        {
            IDatabaseService DBService = WebDatabaseService.CreateDBService(SiteId);
            SiteParam OSiteParam = WebEnvironments.CreateSiteParam(SiteId);
            string AssetCode = WebSessionUtility.GetCurrentLoginUser().AssetCode;
            string DataLanguage = WebConfig.GetDataLanguage(OSiteParam);
            IDbTransaction Trans = DBService.BeginTransaction();
            try
            {
                DBService.ExecuteNonQuery(Trans, 
                    " Delete TablePermissionRoleDetail where frkPermissionRoleId=@PermissionRoleId; "+
                    " Delete TablePermissionRole where PermissionRoleId=@PermissionRoleId; ",
                    new DbParam[]{
                        new DbParam("PermissionRoleId",PermissionRoleId),
                    });

                Trans.Commit();
            }
            catch (Exception ex)
            {
                Trans.Rollback();
                throw (ex);
            }
        }

        public static bool CheckPermission(
            string SiteId, 
            string ptc,
            string PermissionFunctionId,
            string ObjectId,
            string UserId,
            bool ThrowException)
        {
            //WebSessionUtility.CheckSessionTimeOut();
            if (WebSessionUtility.GetCurrentLoginUser() != null)
            {
                if (WebSessionUtility.GetCurrentLoginUser().IsSystemAdmin || WebSessionUtility.GetCurrentLoginUser().IsAdmin == 1)
                {
                    return true;
                }
            }
            IDatabaseService DBService = WebDatabaseService.CreateDBService(SiteId);
            string CheckQuery =
                "   select Allow=IsNull(Allow,0) from TablePermissionRoleDetail" +
                "           join TablePermissionRole on TablePermissionRole.PermissionRoleId=frkPermissionRoleId" +
                "       where ObjectId=@ObjectId and frkPermissionFunctionId=@PermissionFunctionId and frkPermissionTypeId=@PermissionTypeId and type='user' and frkUserId=@UserId and Allow=1";
            DataTable dtResult = DBService.GetDataTable(null, CheckQuery, new DbParam[]{
                new DbParam("PermissionTypeId",ptc),
                new DbParam("UserId",UserId),
                new DbParam("PermissionFunctionId",PermissionFunctionId),
                new DbParam("ObjectId",ObjectId),
            });
            int Allow=0;
            if (dtResult.Rows.Count > 0)
            {
                Allow = Allow + (int)dtResult.Rows[0]["Allow"];
            }
            CheckQuery =
                " select Allow=IsNull(Allow,0) from TablePermissionRoleDetail" +
                "         join TablePermissionRole on TablePermissionRole.PermissionRoleId=frkPermissionRoleId" +
                "   where ObjectId=@ObjectId and frkPermissionFunctionId=@PermissionFunctionId and frkPermissionTypeId=@PermissionTypeId and type='role'" +
                "   and frkRoleId in " +
                "   (" +
                "       select frkRoleId from TableUserRole" +
                "           where TableUserRole.frkUserId=@UserId" +
                "   )";
            dtResult = DBService.GetDataTable(null, CheckQuery, new DbParam[]{
                new DbParam("PermissionTypeId",ptc),
                new DbParam("UserId",UserId),
                new DbParam("PermissionFunctionId",PermissionFunctionId),
                new DbParam("ObjectId",ObjectId),
            });
            if (dtResult.Rows.Count > 0)
            {
                Allow = Allow + (int)dtResult.Rows[0]["Allow"];
            }
            if (ThrowException)
            {
                if (Allow == 0)
                {
                    throw new Exception("Không có quyền truy cập tính năng này!");
                }
            }
            return Allow > 0;
        }
    }
}
